function JavaServer() {
    var _locals = [];
    var _localTypes = [];
    var localIndex = 0;
    function nextLocalIndex() {
        return localIndex++;
    }
    const server = this;

    const ILArray = [];
    const OPCODES = {
        //加载类型
        loadclass: 'loadclass',
        //设置栈顶数据到局部变量表
        stloc: 'stloc',
        //从布局变量表加载数据到栈顶
        ldloc: 'ldloc',
        //设置类型到局部变量类型表
        stloctype: 'stloctype',
        //从局部变量类型表加载类型
        ldloctype: 'ldloctype',
        //加载常量到栈顶
        ldc: 'ldc',
        ldf: 'ldf',
        ldi: 'ldi',
        //静态调用
        call: 'call',
        //静态调用，根据实参自动适配方法签名
        callA: 'callA',
        //实例调用
        callvirtual: 'callvirtual',
        //实例调用，根据实参自动适配方法签名
        callvirtualA: 'callvirtualA',
        //构造实例
        ctor: 'ctor',
        //构造实例，根据实参自动适配构造函数
        ctorA: 'ctorA',
        equal: 'equal',
        NULL: 'null',
        //返回指定局部变量表的数据为结果
        ret: 'ret'
    };

    const TYPES = {
        String: 'java.lang.String',
        Integer: 'java.lang.Integer',
        Double: 'java.lang.Double',
    };

    this.toOpCodes = function () {
        var opCodes = [];
        for (var i = 0; i < ILArray.length; i++) {
            var il = ILArray[i];
            var opCode = il.opCode;
            if (il.args && il.args.length > 0) {
                opCode += ' ' + il.args.join(' ');
            }
            opCodes.push(opCode);
        }
        console.log(opCodes);
        return opCodes;
    };

    this.execute = function () {
        return cal.Js.executeIL(this.toOpCodes());
    };

    this.executeAsync = function (callback) {
        cal.Js.executeILAsync(this.toOpCodes(), callback);
    };

    this.RETURN = function (rVar) {
        //把需要返回的数据放到栈上
        if (typeof rVar === 'object' && rVar.__isLocal) {
            OP(OPCODES.ldloc, rVar.index);
        } else {
            var local = INIT_PARAMETER(rVar);
            OP(OPCODES.ldc, local.index);
        }
        //将栈顶数据返回
        OP(OPCODES.ret);
    };

    this.FOR = function (arrayValues, loopFunc) {

    }

    this.ENDFOR = function () {

    }

    this.IF = function () {

    }

    this.ENDIF = function () {

    }

    this.BREAK = function () {

    }

    this.LOCAL = function (value, type) {
        if (value === undefined) {
            throw new Error('局部变量至少需要一个参数值');
        }
        //把参数存到局部参数表
        if (type !== undefined) {
            OP(OPCODES.ldc, value);
            var local = STLOCAL();
            //把类型参数存到局部参数类型表，参数类型表的索引和参数配置表保持一致 
            STLOCALTYPE(local.index, LOAD_CLASS(type));
        } else {
            return INIT_PARAMETER(value);
        }
        return local;
    }

    this.includeClass = function (className) {
        return this.includeClasses([className]);
    };

    this.includeClasses = function (classNames) {
        var classInfos = cal.Js.getClassInfo(classNames);
        var classArray = []
        for (var i = 0; i < classInfos.length; i++) {
            const classInfo = classInfos[i];
            // createInstanceClass(classInfo.className, classInfo.constructors, classInfo.methods);
            createInstanceClass(classInfo.className, classInfo.methods);
            var clazz = createStaticClass(classInfo.className, classInfo.staticMethods);
            classArray.push(clazz);
        }
        return classArray.length === 1 ? classArray[0] : classArray;
    };

    function createStaticClass(className, methods) {
        var dotIndex = className.lastIndexOf('.');
        if (dotIndex === -1) {
            throw new Error('类路径错误:' + className);
        }
        var packageName = className.substring(0, dotIndex);
        var simpleClassName = className.substring(dotIndex + 1);
        var package = initPackage(packageName);

        package[simpleClassName] = package[simpleClassName] || function () { };
        var classObject = package[simpleClassName];

        for (var i = 0; i < methods.length; i++) {
            var method = methods[i];
            var methodName = method.methodName;
            classObject[methodName] = classObject[methodName] || (function (methodName) {
                return function () {
                    var classIndex = LOAD_CLASS(className);
                    var locals = [];
                    //参数入栈
                    for (var j = arguments.length - 1; j >= 0; j--) {
                        var local = INIT_PARAMETER(arguments[j]);
                        LOAD_PARAMETER(local);
                        locals.push(local);
                    }
                    //类型入栈
                    OP(OPCODES.ldloc, classIndex);
                    //方法名入栈
                    OP(OPCODES.ldc, methodName);

                    //调用方法
                    // var containsType = checkArgumentsType(locals);
                    // if (containsType) {
                    //     OP(OPCODES.call);
                    // } else {
                    //     OP(OPCODES.callA);
                    // }
                    OP(OPCODES.callA);
                    return STLOCAL();
                };
            })(methodName);
        }

        return classObject;
    };

    function createInstanceClass(className, methods) {
        //检查参数
        var dotIndex = className.lastIndexOf('.');
        if (dotIndex === -1) {
            throw new Error('类路径(' + className + ')格式错误');
        }
        //初始化包路径
        var packageName = className.substring(0, dotIndex);
        var simpleClassName = className.substring(dotIndex + 1);
        var package = initPackage(packageName);

        //构造函数
        package[simpleClassName] = package[simpleClassName] || function () {
            //检查参数是否都指定了类型或者都没有指定
            var locals = [];
            //参数入栈
            for (var j = arguments.length - 1; j >= 0; j--) {
                var local = INIT_PARAMETER(arguments[j]);
                LOAD_PARAMETER(local);
                locals.push(local);
            }
            OP(OPCODES.ldloc, LOAD_CLASS(className));

            //调用方法
            // var containsType = checkArgumentsType(locals);
            // if (containsType) {
            //     OP(OPCODES.ctor);
            // } else {
            //     OP(OPCODES.ctorA);
            // }
            OP(OPCODES.ctorA);

            var instance = STLOCAL();
            //把实例对象的索引和标记位存到js实例上
            this.index = instance.index;
            this.__isLocal = instance.__isLocal;

        };
        var classObject = package[simpleClassName];

        //实例方法 
        for (var i = 0; i < methods.length; i++) {
            var method = methods[i];
            var methodName = method.methodName;

            classObject.prototype[methodName] = classObject.prototype[methodName] || (function (methodName) {
                return function () {
                    var locals = [];
                    //参数入栈
                    for (var j = arguments.length - 1; j >= 0; j--) {
                        var local = INIT_PARAMETER(arguments[j]);
                        LOAD_PARAMETER(local);
                        locals.push(local);
                    }

                    OP(OPCODES.ldloc, this.index);
                    OP(OPCODES.ldc, methodName);

                    //检查参数是否都指定了类型或者都没有指定
                    // var containsType = checkArgumentsType(locals);
                    // //调用方法
                    // if (containsType) {
                    //     OP(OPCODES.callvirtual);
                    // } else {
                    //     OP(OPCODES.callvirtualA);
                    // }
                    OP(OPCODES.callvirtualA);

                    return STLOCAL();
                }
            })(methodName);
        }

        return classObject;
    };

    function checkArgumentsType(arguments) {
        var containsTypeCount = 0;
        for (var i = 0; i < arguments.length; i++) {
            var argument = arguments[i];
            if (typeof argument !== 'object' || !argument.__isLocal) {
                continue;
            }
            if (_localTypes[argument.index] !== undefined) {
                containsTypeCount++;
            }
        }
        if (containsTypeCount > 0 && containsTypeCount !== arguments.length) {
            // throw new Error('如果指定了参数类型,则所有参数都必须同时指定类型!');
            return false;
        }
        return containsTypeCount > 0;
    }

    function STLOCAL() {
        var localIndex = nextLocalIndex();
        OP(OPCODES.stloc, localIndex);
        _locals[localIndex] = true;
        return {
            index: localIndex,
            //标识区分普通参数
            __isLocal: true
        };
    }

    function STLOCALTYPE(localIndex, localTypeIndex) {
        OP(OPCODES.ldi, localTypeIndex);
        OP(OPCODES.stloctype, localIndex);
        _localTypes[localIndex] = localTypeIndex;
        return {
            index: localIndex,
            //标识区分普通参数
            __isLocal: true,
            __isLocalType: true,
        };
    }

    var classIndexs = {};
    function LOAD_CLASS(className) {
        var localIndex = classIndexs[className];
        if (localIndex !== undefined) {
            return localIndex;
        }
        OP(OPCODES.ldc, className);
        OP(OPCODES.loadclass);
        localIndex = nextLocalIndex();
        classIndexs[className] = localIndex;
        OP(OPCODES.stloc, localIndex);
        return localIndex;
    }


    function LOAD_PARAMETER(local) {
        validLocal(local);
        OP(OPCODES.ldloc, local.index);
        var localTypeIndex = _localTypes[local.index];
        if (localTypeIndex !== undefined) {
            // OP(OPCODES.ldloc, localTypeIndex);
        }
    }

    function validLocal(value) {
        if (typeof value !== 'object' || !value.__isLocal) {
            throw new Error(value + '不是局部变量~');
        }
    }

    function INIT_PARAMETER(value) {
        if (typeof value === 'object' && value.__isLocal) {
            return value;
        } else if (typeof value === 'string') {
            OP(OPCODES.ldc, value);
            var local = STLOCAL();
            STLOCALTYPE(local.index, LOAD_CLASS(TYPES.String));
            return local;
        } else if (typeof value === 'number') {
            if (isInteger(value)) {
                OP(OPCODES.ldi, value);
                var local = STLOCAL();
                STLOCALTYPE(local.index, LOAD_CLASS(TYPES.Integer));
            } else {
                OP(OPCODES.ldf, value);
                var local = STLOCAL();
                STLOCALTYPE(local.index, LOAD_CLASS(TYPES.Double));
            }
            return local;
        } else {
            throw new Error('不支持此类型的参数:' + value);
        }
    }

    function OP(opCode, args) {
        if (args !== undefined && typeof args !== 'object') {
            args = [args];
        }
        ILArray.push({
            opCode: opCode,
            args: args
        });
    };

    function initPackage(packagePath) {
        if (!packagePath) {
            throw new Error('初始化包对象出错,缺少包路径!');
        }
        var names = packagePath.split('.');
        var currObj = server;
        for (var i = 0; i < names.length; i++) {
            var name = names[i];
            currObj = currObj[name] = currObj[name] || {};
        }
        return currObj;
    };

    function isInteger(obj) {
        return typeof obj === 'number' && obj % 1 === 0;
    }
}

function testCallJava() {
    var server = new JavaServer();
    server.includeClasses([
        'ext.app.process.helper.AttrValueReadHelper',
        'ext.app.process.common.ToolUtils',
        'java.lang.String',
        'java.lang.Object',
        'java.util.HashMap',
    ]);

    var ToolUtils = server.ext.app.process.common.ToolUtils;
    var AttrValueReadHelper = server.ext.app.process.helper.AttrValueReadHelper;

    var obj = ToolUtils.getObjectByOid("OR:com.ptc.windchill.mpml.processplan.MPMProcessPlan:1360434")
    obj = ToolUtils.getLatestPersistable(obj);

    var data = new server.java.util.HashMap1();

    var reader = new AttrValueReadHelper(obj);
    data.put("ciVrOid", reader.getCiVrOid());
    data.put("oid", reader.getOid());
    data.put("number", reader.getNumber());

    server.RETURN(data);

    console.log('执行结果：', server.execute());
    return server;
}

function getObjectByOid(oid) {
    var server = new JavaServer();

    server.includeClasses([
        'ext.app.process.common.ToolUtils',
        'ext.app.process.common.JsonViewUtils',
        'ext.app.process.helper.QsHelper',
    ]);

    var obj = server.ext.app.process.common.ToolUtils.getObjectByOid(oid)
    obj = server.ext.app.process.common.ToolUtils.getLatestPersistable(obj);
    obj = server.ext.app.process.common.JsonViewUtils.getObjInfoMap(obj);

    server.RETURN(obj);

    return server.execute();
}

function testQsHelper() {
    var server = new JavaServer();

    //将类名通过ajax传到后端，反射类信息生成对应的js对象
    server.includeClasses([
        'ext.app.process.helper.AttrValueReadHelper',
        'ext.app.process.helper.QsHelper',
        'java.lang.Class',
        'ext.app.process.common.ToolUtils',
        'ext.app.process.common.JsonViewUtils',
        'java.util.HashMap',
    ]);

    var ToolUtils = server.ext.app.process.common.ToolUtils;
    var AttrValueReadHelper = server.ext.app.process.helper.AttrValueReadHelper;
    var QsHelper = server.ext.app.process.helper.QsHelper;

    //调用js类，生成执行过程中间操作码
    var partClass = server.java.lang.Class.forName('wt.part.WTPartMaster');
    var helper = new QsHelper(partClass);
    helper.equal('WTPartNumber', '13443398');
    var partMaster = helper.findObject(partClass);
    var part = ToolUtils.getLatestPersistable(partMaster);
    var data = new server.java.util.HashMap();
    var reader = new AttrValueReadHelper(part);
    data.put("ciVrOid", reader.getCiVrOid());
    data.put("oid", reader.getOid());
    data.put("number", reader.getNumber());
    data.put("name", reader.getName());
    data.put("version", reader.getFullVersion());
    data.put("typeName", reader.getTypeName());
    data.put("state", reader.getStateNameCN());

    //插入返回data作为结果的指令
    server.RETURN(data);

    //通过ajax回传中间指令并执行指令返回结果
    return server.execute();
}